package com.woniuxy.lab.woniu_lab_boss.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.math.MathUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniuxy.lab.woniu_lab_boss.common.Shell;
import com.woniuxy.lab.woniu_lab_boss.dao.UserDao;
import com.woniuxy.lab.woniu_lab_boss.exception.WebException;
import com.woniuxy.lab.woniu_lab_boss.exception.WebExceptionCode;
import com.woniuxy.lab.woniu_lab_boss.model.Exper;
import com.woniuxy.lab.woniu_lab_boss.dao.ExperDao;
import com.woniuxy.lab.woniu_lab_boss.model.Teacher;
import com.woniuxy.lab.woniu_lab_boss.model.User;
import com.woniuxy.lab.woniu_lab_boss.service.ExperService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.lab.woniu_lab_boss.service.dto.HealthDto;
import com.woniuxy.lab.woniu_lab_boss.service.dto.ExperDto;
import com.woniuxy.lab.woniu_lab_boss.service.dto.TeacherDto;
import com.woniuxy.lab.woniu_lab_boss.util.ShellUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 实验表 服务实现类
 * </p>
 *
 * @author Silas
 * @since 2023-03-15
 */
@Service
public class ExperServiceImpl extends ServiceImpl<ExperDao, Exper> implements ExperService {
    @Resource
    private ExperDao experDao;
    @Resource
    private UserDao userDao;

    @Value("${docker.host}")
    private String host;

    @Value("${docker.username}")
    private String username;

    @Value("${docker.password}")
    private String password;

    @Override
    public IPage<ExperDto> getRunning(Integer page, Integer size) {
        IPage<Exper> iPage = new Page<>(page == null ? 1 : page, size == null ? 4 : size);
        IPage<Exper> page1 = experDao.selectPage(iPage, new QueryWrapper<Exper>().eq("status", "RUNNING"));
        return page1.convert(u -> {
            ExperDto experDto = new ExperDto();
            BeanUtils.copyProperties(u, experDto);
            User user = userDao.selectById(experDto.getUserId());
            experDto.setNickname(user.getNickname());
            return experDto;
        });

    }

    @Override
    public HealthDto getHealth() {
        HealthDto healthDto = new HealthDto();
        // java-ssh实现资源监测
        ShellUtil shellUtil = ShellUtil.getShell(host, username, password);
        Shell shell = shellUtil.getShell();
        healthDto.setCpu(this.getCpu(shell));
        healthDto.setMemory(this.getMemory(shell));
        // 从数据库表查询实例数
        List<Exper> runningExpers = this.list(new QueryWrapper<Exper>().eq("status", "RUNNING").eq("file_or_docker", "DOCKER"));
        healthDto.setInstanceNum(runningExpers.size());

        return healthDto;
    }


    private Double getCpu(Shell shell){

        String allTop = shell.execCommand("top -bn1");
        String cpus = allTop.split("\n")[2];
        String[] cpuInfos = cpus.split(",");
        String cpuFree = cpuInfos[3].replace(" ", "").replace("id", "");
        double cpu = Double.parseDouble(cpuFree);
        double usable = 100.00 - cpu;
        BigDecimal round = NumberUtil.round(usable/100.0, 4);
        return round.doubleValue();
    }

    private Double getMemory(Shell shell) {
        String allMem = shell.execCommand("free -m");
        String MemInfo = allMem.split("\n")[1];
        String temp = MemInfo.replace(" ", ",");
        String[] tempArr = temp.split(",");
        ArrayList<String> strs = new ArrayList<>();
        for(String s : tempArr)
            if(s.length()!=0) strs.add(s);
        String total = strs.get(1).replace(" ", "");
        String unUse = strs.get(strs.size()-1).replace(" ", "");
        double unUseMem = Double.parseDouble(unUse) / Double.parseDouble(total);
        BigDecimal round = NumberUtil.round(1.00 - unUseMem, 4);
        return round.doubleValue();
    }

}
